use binary_heap::binary_heap::{BinaryHeap, BinaryHeapType};
use std::cmp::Ordering;

const NUM_TEST_VALUES: usize = 10000;

fn int_compare(v1: &i32, v2: &i32) -> Ordering {
    v1.cmp(v2)
}

#[test]
fn test_binary_heap_new_free() {
    for _ in 0..NUM_TEST_VALUES {
        let heap = BinaryHeap::new(BinaryHeapType::Min, int_compare);
        assert_eq!(heap.num_entries(), 0);
    }

    // Rust does not have a direct equivalent for testing low memory scenarios
    // as memory allocation is managed by the Rust runtime and Vec.
}

#[test]
fn test_binary_heap_insert() {
    let mut heap = BinaryHeap::new(BinaryHeapType::Min, int_compare);
    let mut test_array = vec![0; NUM_TEST_VALUES];

    for i in 0..NUM_TEST_VALUES {
        test_array[i] = i as i32;
        assert!(heap.insert(test_array[i]));
    }

    assert_eq!(heap.num_entries(), NUM_TEST_VALUES);
}

#[test]
fn test_min_heap() {
    let mut heap = BinaryHeap::new(BinaryHeapType::Min, int_compare);
    let mut test_array = vec![0; NUM_TEST_VALUES];

    for i in 0..NUM_TEST_VALUES {
        test_array[i] = i as i32;
        assert!(heap.insert(test_array[i]));
    }

    let mut i = -1;
    while heap.num_entries() > 0 {
        let val = heap.pop().unwrap();
        assert_eq!(val, i + 1);
        i = val;
        i = val;
    }

    assert_eq!(heap.num_entries(), 0);
    assert!(heap.pop().is_none());
}

#[test]
fn test_max_heap() {
    let mut heap = BinaryHeap::new(BinaryHeapType::Max, int_compare);
    let mut test_array = vec![0; NUM_TEST_VALUES];

    for i in 0..NUM_TEST_VALUES {
        test_array[i] = i as i32;
        assert!(heap.insert(test_array[i]));
    }

    let mut i = NUM_TEST_VALUES as i32;
    while heap.num_entries() > 0 {
        let val = heap.pop().unwrap();
        assert_eq!(val, i - 1);
        i = val;
        i = val;
    }
}

#[test]
fn test_out_of_memory() {
    let mut heap = BinaryHeap::new(BinaryHeapType::Min, int_compare);
    let values = [15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0];

    for i in 0..16 {
        assert!(heap.insert(values[i]));
    }

    assert_eq!(heap.num_entries(), 16);

    // Rust does not have a direct equivalent for testing out of memory scenarios
    // as memory allocation is managed by the Rust runtime and Vec.

    for i in 0..16 {
        let value = heap.pop().unwrap();
        assert_eq!(value, i);
    }

    assert_eq!(heap.num_entries(), 0);
}